package com.hjjt.baselib

import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableList
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import com.hjjt.baselib.HJBaseAdapter.*
import com.hjjt.baselib.util.logError

abstract class HJBaseAdapter<T, B : ViewDataBinding>(
    var dataList: ObservableList<T>,
    val mContext: FragmentActivity,
    val layoutId: Int
) : RecyclerView.Adapter<Holder<B>>() {

    var lifecycleOwner: LifecycleOwner? = null

    val dataChangeCallBack by lazy {
        CallBack()
    }

    var onItemClick: ((index: Int) -> Unit)? = null

    override fun getItemCount(): Int = dataList.size

    fun bindToLifeCycle(lifecycleOwner: LifecycleOwner){
        lifecycleOwner.lifecycle.addObserver(object: LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if(event == Lifecycle.Event.ON_DESTROY){
                    dataList.removeOnListChangedCallback(dataChangeCallBack)
                }
            }
        })
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        dataList.addOnListChangedCallback(dataChangeCallBack)
        bindToLifeCycle(mContext)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        dataList.removeOnListChangedCallback(dataChangeCallBack)
        super.onDetachedFromRecyclerView(recyclerView)

    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder<B> {
        val binding =
            DataBindingUtil.inflate<B>(LayoutInflater.from(mContext), layoutId, parent, false)
        val holder = HJBaseAdapter.Holder(binding)
        return holder
    }

    override fun onBindViewHolder(holder: Holder<B>, position: Int) {
        holder.binding.root.setOnClickListener { onItemClick?.invoke(holder.layoutPosition) }
        initBinding(holder.binding, position)
        setonClick(holder.adapterPosition, holder.binding)
    }

    open fun setonClick(layoutPosition: Int, binding: B) {

    }

    abstract fun initBinding(binding: B, position: Int)

    class Holder<B : ViewDataBinding>(val binding: B) :
        RecyclerView.ViewHolder(binding.root)


    inner class CallBack : ObservableList.OnListChangedCallback<ObservableArrayList<T>>() {
        override fun onChanged(sender: ObservableArrayList<T>?) {
            this@HJBaseAdapter.onChanged(sender)
        }

        override fun onItemRangeChanged(
            sender: ObservableArrayList<T>?,
            positionStart: Int,
            itemCount: Int
        ) {
            this@HJBaseAdapter.onItemRangeChanged(sender, positionStart, itemCount)
        }

        override fun onItemRangeInserted(
            sender: ObservableArrayList<T>?,
            positionStart: Int,
            itemCount: Int
        ) {
            this@HJBaseAdapter.onItemRangeInserted(sender, positionStart, itemCount)
        }

        override fun onItemRangeMoved(
            sender: ObservableArrayList<T>?,
            fromPosition: Int,
            toPosition: Int,
            itemCount: Int
        ) {
            this@HJBaseAdapter.onItemRangeMoved(sender)
        }

        override fun onItemRangeRemoved(
            sender: ObservableArrayList<T>?,
            positionStart: Int,
            itemCount: Int
        ) {
            this@HJBaseAdapter.onItemRangeRemoved(sender, positionStart, itemCount)
        }
    }

    private fun onItemRangeRemoved(
        sender: ObservableArrayList<T>?,
        positionStart: Int,
        itemCount: Int
    ) {
        setNewDatas(sender)
        notifyDataSetChanged()
    }

    private fun onItemRangeMoved(sender: ObservableArrayList<T>?) {
        setNewDatas(sender)
        notifyDataSetChanged()
    }

    private fun onItemRangeInserted(
        sender: ObservableArrayList<T>?,
        positionStart: Int,
        itemCount: Int
    ) {
        setNewDatas(sender)
        notifyDataSetChanged()
    }

    private fun onItemRangeChanged(
        sender: ObservableArrayList<T>?,
        positionStart: Int,
        itemCount: Int
    ) {
        setNewDatas(sender)
        notifyDataSetChanged()
    }

    private fun onChanged(sender: ObservableArrayList<T>?) {
        setNewDatas(sender)
        notifyDataSetChanged()
    }

    private fun setNewDatas(sender: ObservableArrayList<T>?) {
        sender?.let {
            this.dataList = it
        }
    }


}